// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#ifndef __H_MK_RENDER_DEVICE__
#define __H_MK_RENDER_DEVICE__

#include "mk_render_input.h"

namespace MK3DE
{
	class CRenderWindow;
	class CRenderInput;
	class CHardwareBuffer;
	class CTexture2D;
	class CTexture3D;
	class CShader;
	class CRenderTarget;

	//! Render device options.
	/**
	These option should be set before create render device.
	*/
	enum RENDER_DEVICE_OPTION
	{
		RDO_WIDTH, //!< If this value is 0, then engine will take desktop's width.
		RDO_HEIGHT, //!< If this value is 0, then engine will talk desktop's height.
		RDO_COLOR_BIT, //!< Backbuffer's color bit.
		RDO_FULLSCREEN, //!< Whether use full screen display mode.

		RENDER_OP_MAX,
	};

	//! Abstract render device class.
	/*!
	Defined abstract interface for graphic render device.
	*/
	class MK3DE_API CRenderDevice
	{
	public:
		static void SetOption(RENDER_DEVICE_OPTION op, DWORD value);
		static DWORD GetOption(RENDER_DEVICE_OPTION op);

	protected:
		static DWORD _s_options[RENDER_OP_MAX];

	public:
		//! Create render device.
		/**
		\param winHandle : Main window handle.
		\return If the method succeeds, the return value is TRUE. If the method fails, the 
		return value is FALSE.
		*/
		virtual BOOL Create(void* winHandle) = 0;

		//! Begin to render a frame.
		/**
		Before render a frame, this method must be called. If the method failed, the later 
		render operate will fail.
		\return : If the method succeeds, the return value is TRUE. If the method fails, the 
		return value is FALSE.
		*/
		virtual BOOL BeginFrame() = 0;

		//! End to render a frame.
		/**
		After render a frame, this method must be called.
		\return : If the method succeeds, the return value is TRUE. If the method fails, the 
		return value is FALSE.
		*/
		virtual BOOL EndFrame() = 0;

		//! Clear buffer.
		virtual BOOL Clear(BOOL clearBackBuffer, BOOL clearDepth, BOOL clearStencil, DWORD backBufferColor, float depth, DWORD stencil) = 0;

		//! Present back buffer to screen.
		/**
		This method put back buffer to screen display buffer.
		\param pwin : Target render window.
		\return : If the method succeeds, the return value is TRUE. If the method fails, the 
		return value is FALSE.
		*/
		virtual BOOL Present(CRenderWindow* pwin) = 0;

		//! Manage current view port.
		/**
		\param x : Together with y, value describing the coordinate of the upper-left corner of
		the viewport.
		\param y : Together with x, value describing the coordinate of the upper-left corner of
		the viewport
		\param Width : Together with Height, value describing the range of the viewport.
		\param Height : Together with Width, value describing the range of the viewport.
		\param minZ : Together with maxZ, value describing the range of depth values into which 
		a scene is to be rendered, the minimum and maximum values of the clip volume.
		\param maxZ : Together with minZ, value describing the range of depth values into which 
		a scene is to be rendered, the minimum and maximum values of the clip volume
		\return : If the method succeeds, the return value is TRUE. If the method fails, the 
		return value is FALSE.
		*/
		virtual BOOL SetViewport(DWORD x, DWORD y, DWORD Width, DWORD Height, float minZ, float maxZ) = 0;
		virtual void GetViewport(DWORD& x, DWORD& y, DWORD& Width, DWORD& Height, float& minZ, float& maxZ) = 0;

		//! Reisze notification when the size of render target window has changed.
		/**
		The method should be called whenever the size of render target window has changed.
		\param pwin : Render target window.
		\return : If the method succeeds, the return value is TRUE. If the method fails, the 
		return value is FALSE.
		*/
		virtual BOOL OnResize(CRenderWindow* pwin) = 0;

		//! Get back buffer dimension.
		virtual void GetBackBufferDimension(DWORD& width, DWORD& height) = 0;

		//! Get back buffer format.
		virtual PIXEL_FORMAT GetBackBufferFormat() = 0;

		//! Create and destroy render input.
		virtual BOOL CreateRenderInput(RenderInputElemDesc* desc, DWORD descNum, CRenderInput*& renderInput) = 0;
		virtual void DestroyRenderInput(CRenderInput*& pRenderInput) = 0;

		//! Create and destroy vertex buffer.
		virtual BOOL CreateVertexHardwareBuffer(DWORD vertexSize, DWORD vertexNum, HARDWARE_BUFFER_USAGE usage, CHardwareBuffer*& buffer) = 0;
		virtual void DestroyVertexHardwareBuffer(CHardwareBuffer*& pBuffer) = 0;

		//! Create and destroy index buffuer.
		virtual BOOL CreateIndexHardwareBuffer(DWORD indexNum, INDEX_TYPE indexType, HARDWARE_BUFFER_USAGE usage, CHardwareBuffer*& buffer) = 0;
		virtual void DestroyIndexHardwareBuffer(CHardwareBuffer*& pBuffer) = 0;

		//! Create and destroy 2d texture.
		virtual BOOL CreateTexture2DFromFile(const char* fileName, CTexture2D*& pTexture) = 0;
		virtual BOOL CreateTexture2DFromMemory(const BYTE* buffer, DWORD size, CTexture2D*& pTexture) = 0;
		virtual BOOL CreateTexture2D(DWORD width, DWORD height, PIXEL_FORMAT format, DWORD mip, TEXTURE_USAGE usage, CTexture2D*& pTexture) = 0;
		virtual void DestroyTexture2D(CTexture2D*& pTexture2D) = 0;

		//! Create and destroy 3d texture.
		virtual BOOL CreateTexture3DFromFile(const char* fileName, CTexture3D*& pTexture) = 0;
		virtual void DestroyTexture3D(CTexture3D*& pTexture) = 0;

		//! Create and destroy shader.
		virtual BOOL CreateShaderFromFile(const char* fileName, CShader*& shader) = 0;
		virtual BOOL CreateShaderFromMemory(const BYTE* buffer, DWORD size, CShader*& shader) = 0;
		virtual void DestroyShader(CShader*& pShader) = 0;

		//! Create render target.
		virtual BOOL CreateRenderTarget(DWORD width, DWORD height, PIXEL_FORMAT format, BOOL bDSBuffer, CRenderTarget*& pRenderTarget) = 0;
		virtual void DestroyRenderTarget(CRenderTarget*& pRenderTarget) = 0;

		//! Bind render input for current rendering.
		virtual BOOL BindRenderInput(CRenderInput* renderInput) = 0;

		//! Render primitives.
		virtual BOOL DrawPrimitive(PRIMITIVE_TYPE primitiveType, DWORD firstVertex, DWORD minIndex, DWORD vertexNum, DWORD firstIndex, DWORD primitiveNum) = 0;

		//! Set textures for current rendering.
		virtual BOOL SetTexture(DWORD stage, CTexture2D* pTexture) = 0;

		//! Manage render target.
		/**
		\param pRenderTarget : new render target. To reset to default render target, pass NULL.
		\return : Succeed or not.
		*/
		virtual BOOL SetRenderTarget(CRenderTarget* pRenderTarget) = 0;

		//! Set render state.
		virtual BOOL SetRenderState(RENDER_STATE state, DWORD value) = 0;

		//! Get the max texture size supported by current render device.
		virtual DWORD GetMaxTextureSize() = 0;

		//! Manage clip plane. 
		virtual BOOL SetClipPlane(DWORD index, D3DXPLANE& plane, BOOL enable) = 0;
		virtual BOOL EnableClipPlane(DWORD index, BOOL enable) = 0;

	};
};

#endif // __H_MK_RENDER_DEVICE__